/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package JFreeChartExtensions.chartextensions.utils;

import JFreeChartExtensions.ChartPanelDialogs.SelectAverageDialog;
import JFreeChartExtensions.chartextensions.averageloader.AverageLoaderManager;
import JFreeChartExtensions.Collections.DatasetCollection;
import JFreeChartExtensions.ExtendableChartPanel;
import gnu.trove.iterator.TDoubleIterator;
import gnu.trove.list.array.TDoubleArrayList;
import java.awt.geom.Rectangle2D;
import java.util.LinkedList;
import java.util.List;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.xy.XYIntervalSeries;

/**
 *
 * @author Nobody
 */
public class AverageCalculator  {

    private ExtendableChartPanel chartPanel;
    private AverageLoaderManager manager;
  //  private ProgressDialog progressDialog;
    private int x1;
    private int x2;
    private int y1;
    private int y2;
    private int seriesIdx;
    private int interval;

    public int getInterval() {
        return interval;
    }

    public void setInterval(int interval) {
        this.interval = interval;
    }

    public int getSeriesIdx() {
        return seriesIdx;
    }

    public void setSeriesIdx(int seriesIdx) {
        this.seriesIdx = seriesIdx;
    }

    public int getX1() {
        return x1;
    }

    public int getX2() {
        return x2;
    }

    public int getY1() {
        return y1;
    }

    public int getY2() {
        return y2;
    }

    public void setX1(int x1) {
        this.x1 = x1;
    }

    public void setX2(int x2) {
        this.x2 = x2;
    }

    public void setY1(int y1) {
        this.y1 = y1;
    }

    public void setY2(int y2) {
        this.y2 = y2;
    }

    public int getWidth() {
        return this.x1 - this.x2;

    }

    public int getHeight() {
        return this.y1 - this.y2;

    }

   /* public ProgressDialog getProgressDialog() {
        return progressDialog;
    }*/

    public AverageCalculator(ExtendableChartPanel chartPanel, AverageLoaderManager loaderManager) {
        this.chartPanel = chartPanel;
        this.manager = loaderManager;
    }

    public List<XYIntervalSeries> getAllSeriesThatHasPointsInSelection() {
        Rectangle2D area = constructRectangleFromClickedPoints();
        return getAllSeriesThatHasPointsInSelection(area);
    }

    public List<XYIntervalSeries> getAllSeriesThatHasPointsInSelection(Rectangle2D area) {
      //  XYReggresionSeriesCollection collection = ((XYReggresionSeriesCollection) chartPanel.getChart().getXYPlot().getDataset());
        List<XYIntervalSeries> list = new LinkedList<XYIntervalSeries>();
        DatasetCollection collection = chartPanel.getDatasetCollection();
        for (XYIntervalSeries intervalSeries : collection.getSeriesList()) {
            boolean founded = false;
            for (int i = 0; founded == false && i < intervalSeries.getItemCount(); ++i) {
                double xCurrent = (Double) intervalSeries.getX(i);
                double yCurrent = (Double) intervalSeries.getYValue(i);
                if (area.contains(xCurrent, yCurrent)) {
                    founded = true;
                }
            }
            if (founded) {
                list.add(intervalSeries);
            }
        }
        return list;
    }

    private int[] getIndicesOfBorderItemInArea(XYIntervalSeries intervalSeries, Rectangle2D area) {
        int[] borderItems = new int[2];
        boolean foundedFirstItem = false;
        boolean foundedSecondItem = false;
        for (int i = 0; i < intervalSeries.getItemCount(); ++i) {
            double xCurrent = (Double) intervalSeries.getX(i);
            if (xCurrent >= area.getMinX() && !foundedFirstItem) {
                foundedFirstItem = true;
                borderItems[0] = i;
            } else if (xCurrent > area.getMaxX() && foundedFirstItem) {
                foundedSecondItem = true;
                borderItems[1] = i - 1;
                return borderItems;
            }
        }
        if (!foundedSecondItem) {
            borderItems[1] = intervalSeries.getItemCount() - 1;
            return borderItems;
        }
        throw new IllegalStateException("Error in getting border items for average loading");
    }

    private void calculateAverageForSeriesTest(XYIntervalSeries intervalSeries, int interval, Rectangle2D area) {

      /*  DefaultBoundedRangeModel model = (DefaultBoundedRangeModel) progressDialog.getProgress().getModel();

        int[] items = getIndicesOfBorderItemInArea(intervalSeries, area);

        model.setMaximum(100);
        model.setMinimum(0);
        model.setValue(0);
        if (interval > Math.abs(items[0] - items[1]) + 1) {
            throw new IllegalStateException("Interval cannot be grater that amount of selected points.");
        }
        double[] x = new double[interval];
        double[] y = new double[interval];
        System.out.println(String.format("Start : %d End : %d", items[0], items[1]));
        progressDialog.setLogMessage("Calculating points...");
        int end = items[1];
        int pointIndex = -1;
        for (int i = items[0]; i <= items[1]; ++i) {
            double xCurrent = (Double) intervalSeries.getX(i);
            double yCurrent = (Double) intervalSeries.getYValue(i);
            if (area.contains(xCurrent, yCurrent)) {
                x[++pointIndex] = xCurrent;
                y[pointIndex] = yCurrent;
            }
            if (pointIndex == x.length - 1) {
                for (double item : x) {
                    intervalSeries.remove(new Double(item));
                }
                double value = (((double) (i - items[0])) / (double) (end - items[0] ) * 100);
                model.setValue((int) value);
                Rectangle progressRect = progressDialog.getProgress().getBounds();
                progressRect.x = 0;
                progressRect.y = 0;
                progressDialog.getProgress().paintImmediately(progressRect);
                progressDialog.setPercent(value);
                items[1] = items[1] - pointIndex;
                i -= pointIndex;
                double averageX = getAverage(x, pointIndex);
                double averageY = getAverage(y, pointIndex);
                pointIndex = -1;
                intervalSeries.add(averageX, averageX, averageX, averageY, averageY, averageY);
                System.out.println(String.format("CurrentItem %d", i));
            }
        }
        if (pointIndex != - 1) {
            double averageX = getAverage(x, pointIndex);
            double averageY = getAverage(y, pointIndex);
            pointIndex = -1;
            intervalSeries.add(averageX, averageX, averageX, averageY, averageY, averageY);
            model.setValue((int) 100);
                Rectangle progressRect = progressDialog.getProgress().getBounds();
                progressRect.x = 0;
                progressRect.y = 0;
                progressDialog.getProgress().paintImmediately(progressRect);
                progressDialog.setPercent(100);
               
        }
        progressDialog.setLogMessage("Painting...");
        manager.setProgressDialog(progressDialog);
    }

    @Override
    public void perform(ProgressDialog dialog) {
        this.progressDialog = dialog;
        average();*/
    }

    public void average() {
     /*   Rectangle2D area = constructRectangleFromClickedPoints();
        List<XYIntervalSeries> listOfSeries = getAllSeriesThatHasPointsInSelection(area);
        if (listOfSeries.isEmpty()) {
            return;
        }
        calculateAverageForSeriesTest(listOfSeries.get(seriesIdx), interval, area);
        chartPanel.updateChart();
        chartPanel.repaint();
        manager.setDraw(false);*/
    }

    private double getAverage(TDoubleArrayList list) {
        double sum = 0;
        for (TDoubleIterator iter = list.iterator(); iter.hasNext();) {
            sum += iter.next();
        }
        return sum / list.size();
    }

    private double getAverage(double[] list, int pointIndex) {
        double sum = 0;
        for (int i = 0; i <= pointIndex; ++i) {
            sum += list[i];
        }
        return sum / (double) (pointIndex + 1);
    }

    private Rectangle2D constructRectangleFromClickedPoints() {
        XYPlot plot = chartPanel.getChart().getXYPlot();
        ValueAxis domainAxis = plot.getDomainAxis();
        ValueAxis rangeAxis = plot.getRangeAxis();
        double xStart = domainAxis.java2DToValue(x1, chartPanel.getScreenDataArea(), plot.getDomainAxisEdge());
        double yStart = rangeAxis.java2DToValue(y1, chartPanel.getScreenDataArea(), plot.getRangeAxisEdge());
        double xEnd = domainAxis.java2DToValue(x2, chartPanel.getScreenDataArea(), plot.getDomainAxisEdge());
        double yEnd = rangeAxis.java2DToValue(y2, chartPanel.getScreenDataArea(), plot.getRangeAxisEdge());

        if (xEnd < xStart) {
            double tmp = xEnd;
            xEnd = xStart;
            xStart = tmp;
        }
        if (yEnd < yStart) {
            double tmp = yEnd;
            yEnd = yStart;
            yStart = tmp;
        }
        return new Rectangle2D.Double(xStart, yStart, xEnd - xStart, yEnd - yStart);
    }

    public void showGUI() {
        if (getAllSeriesThatHasPointsInSelection().isEmpty()) {
            manager.setDraw(false);
            chartPanel.repaint();
            return;
        }

        java.awt.EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new SelectAverageDialog(chartPanel, AverageCalculator.this).setVisible(true);
            }
        });

    }
}
